<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>内存泄漏和释放(Memory leakage and release)</title>
  <!-- 
  在JavaScript中，内存泄漏（Memory Leakage）是指程序在运行时未能释放不再使用的内存，从而导致可用内存逐渐减少，最终可能导致性能下降或程序崩溃。内存管理是JavaScript引擎的一个重要方面，理解内存泄漏的原因及其解决方法对于开发高效的应用程序至关重要。
  一、内存泄漏的原因
  1. 全局变量：
    - 不小心将变量定义为全局变量，导致它们在整个应用程序生命周期中保持引用，无法被垃圾回收。
    function createGlobalVariable() {
        globalVar = 'I am a global variable'; // 忘记使用 var/let/const
    }
    createGlobalVariable();
  2. 未清除的事件监听器：
    - 如果在添加事件监听器后未能适时移除它们，可能会导致内存泄漏，尤其是在涉及DOM元素的情况下。
    const button = document.getElementById('myButton');
    button.addEventListener('click', function handler() {
        console.log('Button clicked');
    });
    // 如果不移除监听器，按钮被删除后，handler 仍然存在于内存中
  3. 闭包：
    - 闭包可能会导致内存泄漏，特别是当闭包持有对外部作用域的引用时，且这些引用不再需要时。
    function createClosure() {
        let largeArray = new Array(1000000).fill('data');
        return function() {
            console.log(largeArray);
        };
    }
    const closure = createClosure();
    // largeArray 仍然在内存中，即使 createClosure() 已经返回
  4. 定时器和回调：
    - 使用  `setInterval`  或  `setTimeout`  时，如果不清除定时器，可能会导致内存泄漏。
    let timer = setInterval(function() {
        console.log('Running...');
    }, 1000);
    // 如果不调用 clearInterval(timer)，则定时器将一直存在

  二、内存释放
  JavaScript 使用垃圾回收（Garbage Collection）机制自动管理内存。垃圾回收器会定期检查不再使用的对象并将其释放，以便回收内存。以下是一些常见的内存释放机制：
  1. 引用计数：
    - 每个对象都有一个引用计数器，当引用计数为零时，垃圾回收器会回收该对象的内存。

  2. 标记-清除算法：
    - 垃圾回收器会标记所有可达的对象，然后清除未被标记的对象，从而释放内存。

  三、避免内存泄漏的最佳实践
  1. 使用局部变量：
    - 尽量使用局部变量而不是全局变量，避免不必要的全局引用。

  2. 清除事件监听器：
    - 在不再需要时，及时移除事件监听器。
    button.removeEventListener('click', handler);
  3. 清理定时器：
    - 使用  `clearTimeout`  和  `clearInterval`  清除定时器。

  4. 避免不必要的闭包：
    - 确保闭包只在必要时使用，避免持有不再需要的引用。

  5. 使用工具：
    - 使用浏览器的开发者工具（如 Chrome 的内存分析工具）来监测内存使用情况，查找潜在的内存泄漏。

  四、总结
  - 内存泄漏是指程序未能释放不再使用的内存，导致性能问题。
  - 常见的内存泄漏原因包括全局变量、未清除的事件监听器、闭包和未清理的定时器。
  - JavaScript 使用垃圾回收机制自动管理内存，但开发者仍需遵循最佳实践以避免内存泄漏。
    -->
</head>
<body>

  <script>
     function createAdder(count) {
      function adder(num) {
        return count + num
      }

      return adder
    }

    var adder5 = createAdder(5)
    adder5(100)
    adder5(55)
    adder5(12)

    var adder8 = createAdder(8)
    adder8(22)
    adder8(35)
    adder8(7)

    console.log(adder5(24))
    console.log(adder8(30))

    // 永远不会再使用adder8
    // 内存泄漏: 对于那些我们永远不会再使用的对象, 但是对于GC来说, 它不知道要进行释放的对应内存会依然保留着
    adder8 = null
  </script>
  
</body>
</html>